package com.cci.kangdao.service.impl;

import com.cci.kangdao.aop.UserThreadLocal;
import com.cci.kangdao.azureAD.AzureADTool;
import com.cci.kangdao.common.RedisKeys;
import com.cci.kangdao.dao.*;
import com.cci.kangdao.dao.model.RelationShipT;
import com.cci.kangdao.dao.model.UserT;
import com.cci.kangdao.enums.GMApplyRecordStatus;
import com.cci.kangdao.redis.RedisClientUtils;
import com.cci.kangdao.service.GMApplyRecordFlowService;
import com.cci.kangdao.service.GMApplyService;
import com.cci.kangdao.service.PropertiesUtils;
import com.cci.kangdao.utilTool.*;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Service("gmApplyService")
public class GMApplyServiceImpl implements GMApplyService {

	@Autowired
	private GMApplyDao gmApplyDao;
	@Resource
	private GMApplyRecordTDao gmApplyRecordTDao;
	@Autowired
	private RedisClientUtils redisClientUtils;
	@Autowired
	private LoginDao loginDao;
	@Autowired
	private PropertiesUtils propertiesUtils;
	@Autowired
	private RelationShipTDao relationShipTDao;
	@Autowired
	private UserTDao userTDao;
	
	@Autowired
	private GMApplyRecordFlowService gMApplyRecordFlowService;
	
	
	@Autowired
	private GMVisitorDao gmVisitorDao;
	
	
	private Logger log = Logger.getLogger(this.getClass().getName());
	
	private static final String TO_BE_APPROVED_MSG = "您有一条Guidanz权限申请需要审批，请尽快处理！申请人（姓名：%s；手机号：%s）";
	private static final String APPROVED_MSG = "您的Guidanz权限申请审核已通过，可正常登录并使用Guidanz！";
	private static final String DEAUTHORIZATION_MSG = "您的Guidanz权限已被解除，如有问题请联系管理员（手机号：%s）！";
	private static final String OVERTIME_MSG = "您的Guidanz权限将于明日过期，您可重新申请相关权限！";
	private static final String OVERTIME_MSG_15D = "您的Guidanz权限将于%s过期，您可重新申请相关权限！";
	private static final String OVERTIME_MSG_30D = "您的Guidanz权限将于%s过期，您可重新申请相关权限！";
	private static final String TO_BE_APPROVED_OVERTIME_MSG = "您提交的Guidanz权限申请未审批，请联系审批人（姓名：%s；手机号：%s）";
	
	private static final int TO_AUDIT = 1;
	private static final int TO_APPLY = 2;
	
	private static final int INNER_TYPE = 2;
	
	@Override
	public ModelAndView qualityCheck(Map<String, Object> map) throws Exception {
		JSONObject obj = new JSONObject();
		//1.提取参数信息
		HttpServletResponse response = (HttpServletResponse)map.get("response");
		HttpServletRequest request = (HttpServletRequest) map.get("request");
		
		UserT user = getUserInfo(request);
		//2.验证用户是否可申请GM权限 OEM和普通用户不可申请
		if(user.getIsType() == 0 || user.getIsType() == 4 || user.getIsType() == 5) {
			obj.put("data", "");
			obj.put("status", 2);
			obj.put("msg", "您暂时不能申请Guidanz权限");
			ParameterTool.writeResponse(response, obj.toString());	
			return null;
		}
		
		//3.验证所属企业是否可申请GM权限
//		String flag = getGMControlFlag();
//		if(StringUtils.isNotBlank(flag) && flag.equals("OPEN")) {
//			//有进行企业权限验证，需要验证用户所属企业是不是在授权范围内
//
//			boolean cheFlag;
//			if(user.getIsType() == 6) {
//				cheFlag = checkCompanyControl(user.getServiceStationID(), 2);
//			} else {
//				cheFlag = checkCompanyControl(user.getCompanyId(), 1);
//			}
//
//			if(!cheFlag) {
//				obj.put("data", "");
//				obj.put("status", 2);
//				obj.put("msg", "您所在企业（" + (user.getIsType() == 6? user.getStationName(): user.getCompanyName()) + "）暂不能申请Guidanz权限");
//				ParameterTool.writeResponse(response, obj.toString());
//				return null;
//			}
//		}
		
		//4.验证是否有“待审核”状态或者“已授权”状态的申请
		if(gmApplyDao.checkUserApply0(user.getId()) > 0 ) {
			obj.put("status", 4);
			obj.put("msg", "已申请Guidanz权限");
		} else {
			obj.put("status", 0);
			obj.put("msg", "Success");
		}
		
		if(gmApplyDao.checkUserApply2(user.getId()) > 0) {
			obj.put("status", 5);
			obj.put("msg", "有已授权Guidanz权限");
		}
		//5.整合用户基本信息
		String companyName = "";
		String companyNo = "";
		int companyType = 1;
		if(user.getIsType() == 6) {
			companyName = user.getStationName();
			companyNo = gmApplyDao.getStationNo(user.getServiceStationID());
			companyType = 2;
		} else {
			companyName = user.getCompanyName();
			companyNo = gmApplyDao.getCompanyNo(user.getCompanyId());
		}
		
		Map<String, Object> retMap = new HashMap<>();
		retMap.put("userName", user.getContact());
		retMap.put("userPhone", user.getPhone());
		retMap.put("wwid", user.getType() == INNER_TYPE? user.getUserName(): "");
		retMap.put("companyId", user.getCompanyId());
		retMap.put("companyNo", companyNo);
		retMap.put("companyName", companyName);
		retMap.put("companyType", companyType);
		retMap.put("usergroupId", user.getUsergroupId());
		//6.GM服务类型数据
		retMap.put("serviceLevelList", getSGSTList());
		//6.整理数据返回APP
		obj.put("data", retMap);
		ParameterTool.writeResponse(response, obj.toString());	
		
		return null;
	}
	

	

	@Override
	@Transactional
	public ModelAndView createGMApply(Map<String, Object> map) throws Exception {
		JSONObject obj = new JSONObject();
		//1.提取参数信息
		HttpServletResponse response = (HttpServletResponse)map.get("response");
		HttpServletRequest request = (HttpServletRequest) map.get("request");
		
		UserT user = getUserInfo(request);
		
		String serviceType = request.getParameter("serviceType");
		//参数校验
		if(StringUtils.isBlank(serviceType)) {
			obj.put("data", "");
			obj.put("status", 3);
			obj.put("msg", "请选择服务类型");
			ParameterTool.writeResponse(response, obj.toString());	
			return null;
		}
		
		//2.验证当前用户所属企业是否有审核人
		List<Map<String, Object>> auditList = getAuditUser(user);
		if(CollectionUtils.isEmpty(auditList)) {
			obj.put("data", "");
			obj.put("status", 2);
			obj.put("msg", "您所在企业暂无Guidanz权限审核人员，请联系系统管理员及时配置审核人员！");
			ParameterTool.writeResponse(response, obj.toString());	
			return null;
		}
		
		String current = LocalTimeUtil.getRealCurrentTime();
		
		
		//3.检查是否有待审核状态的申请并处理
		/*	if(gmApplyDao.checkUserApply0(user.getId()) > 0 ) {
				gmApplyDao.updateApplyRecordStatusToWD(1, user.getId(), current, 0);
			}*/
		
		// 生成一条访客记录
		long userId = user.getId();
		if(gmVisitorDao.countByUserId(userId) <= 0) {
			GMVisitorEntity visitor = new GMVisitorEntity(userId, userId, current);
			gmVisitorDao.insertSelective(visitor );
		}
		
		
		/**
		 * 新旧系统兼容
		 * 把状态为审核中(站长审核中、管理员审核中)的申请单修改为撤消状态
		 * 1.查询出当前用户处于审核中的(站长审核中、管理员审核中)申请单(只包含带权限级别的申请单)
		 * 2.并将其修改成撤消状态
		 */
		List<Map<String, Object>> auditApplyRecordList = gmApplyRecordTDao.getAuditApplyRecordsByUserId(user.getId());
		
		// 将申请单置为撤消状态
		if(!CollectionUtils.isEmpty(auditApplyRecordList)) {
		
			log.info("撤销当前用户的权限申请单(站长或管理员审核中)");
			
			for(Map<String, Object> auditRecord : auditApplyRecordList) {
				// 在撤消申请单时，如果申请单状态还是(站长审核中、管理员审核中)则撤消，否则不撤消
				Long recordId = MapUtils.getLong(auditRecord, "ID");
				Map<String, Object> updateMap = new HashMap<>();
				updateMap.put("recordId", recordId);
				updateMap.put("status", GMApplyRecordStatus.USER_WITHDRAW.getStatus());
				updateMap.put("updator", user.getId());
				updateMap.put("updateTime", current);
				int result = gmApplyRecordTDao.doWithdrawApplyRecordById(updateMap);
				
				int applySource = MapUtils.getIntValue(auditRecord, "ApplySource", 0);
				// 当前申请单是由Guidanz-App所申请，那么需要对当前申请单生成流水
				// 旧系统申请的权限单，目前不生成流水
				if(result > 0 && applySource == 1) {
					log.info(String.format("ID：%s 生成操作流水", recordId));
					// 查询出最新的操作流水
					Map<String, Object>  recordFlow = gMApplyRecordFlowService.getNewestApplyRecordFlowByRecordId(recordId);
					recordFlow.put("ApplyRecordStatus", GMApplyRecordStatus.USER_WITHDRAW.getStatus());
					recordFlow.put("Description", GMApplyRecordStatus.USER_WITHDRAW.getDesc());
					recordFlow.put("Remark", "用户申请新的权限，旧的权限被撤销");
					recordFlow.put("Creator", user.getId());
					recordFlow.put("CreateTime", current);
					gMApplyRecordFlowService.saveApplyRecordFlow(recordFlow);
				}
				
			}
		}
			
		
		
		
		//5.创建申请记录
		String companyNo = request.getParameter("companyNo");
		String companyName = request.getParameter("companyNo");
		
		if(StringUtils.isBlank(companyNo)) {
			if(user.getIsType() == 6) {
				companyNo = gmApplyDao.getStationNo(user.getServiceStationID());
			} else {
				companyNo = gmApplyDao.getCompanyNo(user.getCompanyId());
			}
			map.put("companyNo", companyNo);
		}
		
		if(StringUtils.isBlank(companyName)) {
			if(user.getIsType() == 6) {
				companyName = user.getStationName();
			} else {
				companyName = user.getCompanyName();
			}
			map.put("companyName", companyName);
		}
		
		map.put("userId", user.getId());
		map.put("applyTime", current);
		map.put("createTime", current);
		map.put("creator", user.getId());
		map.put("companyId", user.getIsType() == 6? user.getServiceStationID(): user.getCompanyId());
		map.put("companyType", user.getIsType() == 6? 2: 1);
		map.put("status", 0);
		int intRes = gmApplyDao.insertApplyRecord(map);
		
		if(intRes <= 0) {
			obj.put("data", "");
			obj.put("status", 1);
			obj.put("msg", "系统异常");
			ParameterTool.writeResponse(response, obj.toString());	
			return null;
		}
		
		//添加审核记录，并发送消息给审核人
		String msg = String.format(TO_BE_APPROVED_MSG, user.getContact(), user.getPhone());
		auditList.forEach(m -> {
			m.put("recordId", map.get("id"));
			m.put("status", 0);
			m.put("creator", user.getId());
			m.put("createTime", current);
			int rf = gmApplyDao.insertAuditRecord(m);
			if(rf > 0) {
				//发送短信及消息推送
				if(sendMsg(m, msg)) {
					//记录消息推送记录
					saveNotice(Long.valueOf(map.get("id").toString()), current, TO_AUDIT, Long.valueOf(m.get("ID").toString()), user.getId(), msg);
				}
			}
		});
		
		obj.put("data", "");
		obj.put("status", 0);
		obj.put("msg", "Success");
		ParameterTool.writeResponse(response, obj.toString());	
		
		return null;
	}

	@Override
	@Transactional
	public ModelAndView deauthorization(Map<String, Object> map) throws Exception {
		JSONObject obj = new JSONObject();
		HttpServletResponse response = (HttpServletResponse)map.get("response");
		HttpServletRequest request = (HttpServletRequest) map.get("request");
		
		String recordId = request.getParameter("recordId");
		String reason = request.getParameter("reason");
		
		if(StringUtils.isBlank(recordId) || StringUtils.isBlank(reason)) {
			obj.put("data", "");
			obj.put("status", 1);
			obj.put("msg", "系统异常");
			ParameterTool.writeResponse(response, obj.toString());	
			return null;
		}
		
		UserT user = getUserInfo(request);
		String current = LocalTimeUtil.getRealCurrentTime();
		//1. 修改申请记录状态及相关信息
		Map<String, Object> pMap = new HashMap<>();
		pMap.put("ID", recordId);
		pMap.put("DeauthorizeTime", current);
		pMap.put("DeauthorizeReason", reason);
		pMap.put("Status", 4);
		pMap.put("Updator", user.getId());
		pMap.put("UpdateTime", current);
		gmApplyRecordTDao.updateGMApplyRecord(pMap);
		
		//2. 修改AD字段数据
		Map<String, Object> userInfo = gmApplyDao.getApplyUserInfo(Long.valueOf(recordId));
		Integer type = Integer.valueOf(userInfo.get("Type").toString());
		updateADCustomerAttributes(userInfo.get("UserName").toString(), type, null, null, "");
		//3. 告知申请人
		if(!String.valueOf(user.getId()).equals(userInfo.get("ID").toString())) {
			//如果撤回人和申请人的ID不同，则通知申请人
			String msg = String.format(DEAUTHORIZATION_MSG, user.getPhone());
			sendMsg(userInfo.get("Phone").toString(), userInfo.get("UserName").toString(), msg);
			saveNotice(Long.valueOf(recordId), current, TO_APPLY, Long.valueOf(userInfo.get("ID").toString()), user.getId(), msg);
		}
		
		//3. 非CCI员工申请，需要修改电子服务工具订单可用GM数量
		Object orderId = userInfo.get("OrderId");
		if(null != orderId && StringUtils.isNotBlank(orderId.toString())) {
			gmApplyDao.releaseOneResause(Long.valueOf(orderId.toString()));
		}
		
		obj.put("data", "");
		obj.put("status", 0);
		obj.put("msg", "Success");
		ParameterTool.writeResponse(response, obj.toString());	
		return null;
	}

	@Override
	@Transactional
	public ModelAndView approveApply(Map<String, Object> map) throws Exception {
		JSONObject obj = new JSONObject();
		HttpServletResponse response = (HttpServletResponse)map.get("response");
		HttpServletRequest request = (HttpServletRequest) map.get("request");
		
		UserT user = getUserInfo(request);
		
		Long orderId = null;
		if(null != map.get("orderId") && StringUtils.isNotBlank(map.get("orderId").toString())) {
			orderId = Long.valueOf(map.get("orderId").toString());
			// 非CCI员工申请，先判断是否还有审批额度
			Map<String,Object> userOrganizationType = userTDao.getUserOrganizationType(user.getId());
			int organizationType = 0;   //组织类型
			long organizationId = 0;   //组织id
			if(MapUtils.isNotEmpty(userOrganizationType)){
				int isType = MapUtils.getIntValue(userOrganizationType,"IsType");
				if(isType == 1 || isType == 3){
					organizationType = 1;
					organizationId = MapUtils.getLongValue(userOrganizationType,"CompanyID");
				} else if(isType == 6){
					organizationType = 2;
					organizationId = MapUtils.getLongValue(userOrganizationType,"ServiceStationID");
				}
			}
			int usableGMNum = gmApplyRecordTDao.getUsableGMNum(organizationType,organizationId);
			if (usableGMNum < 1){
                obj.put("data", "您的企业名称下所有INSITE订单均已被授权，当前无INSITE订单可用，无法授权新Guidanz用户，请知悉");
                obj.put("status", 3);
                obj.put("msg", "您的企业名称下所有INSITE订单均已被授权，当前无INSITE订单可用，无法授权新Guidanz用户，请知悉");
                ParameterTool.writeResponse(response, obj.toString());
                return null;
            }
			//3. 非CCI员工申请，需要修改电子服务工具订单可用GM数量
			int occupyNo = gmApplyDao.occupyOneResause(orderId);
			if(occupyNo == 0) {
				obj.put("data", "请联系康明斯相关支持人员");
				obj.put("status", 2);
				obj.put("msg", "请联系康明斯相关支持人员");
				ParameterTool.writeResponse(response, obj.toString());	
				return null;
			}
		}
		
		String current = LocalTimeUtil.getRealCurrentTime();
		Long recordId = Long.valueOf(map.get("recordId").toString());
		
		//获取申请人信息
		Map<String, Object> userInfo = gmApplyDao.getApplyUserInfo(recordId);
		//4.检查是否有已授权状态的申请并处理
		Long applyId = Long.valueOf(userInfo.get("ID").toString());
		String applyName = userInfo.get("UserName").toString();
		Integer type = Integer.valueOf(userInfo.get("Type").toString());
		
		boolean hasBeta = false;
		//处理已审核通过的申请记录并释放占用资源
		if(gmApplyDao.checkUserApply2(applyId) > 0) {
			
			// 获取用户审核通过的权限(用户只会有一个审核通过的权限申请单)
			Map<String, Object> userApplyRecord = gmApplyDao.getUserApplyRecordByUserId(applyId);
			
			if(MapUtils.isNotEmpty(userApplyRecord)) {
				
				/**
				 * applySource 参数说明：
				 * 0：由旧系统申请的权限  1：由Guidanz-App申请的权限  2：由web端申请的权限
				 */
				int applySource = MapUtils.getIntValue(userApplyRecord, "ApplySource", 0);
				int oldVersion = MapUtils.getIntValue(userApplyRecord, "Version", 0);
				
				String oldServiceType = MapUtils.getString(userApplyRecord, "ServiceType","");
				String oldServiceUptodateType = MapUtils.getString(userApplyRecord, "ServiceUptodateType","");
				Long oldRecordId = MapUtils.getLong(userApplyRecord, "ID");
				
				// 旧系统还沿用旧逻辑不变，只是增加了对Guidanz-App申请的权限申请单被修改后，需要生成流水
				if(applySource == 1 || applySource == 2) {
					
					// 当前用户拥有的权限不包含Beta权限时
					if(!oldServiceUptodateType.contains("BTGF")) {
						// 将旧权限修改为解除状态，并生成操作流水
						Map<String, Object> oldRecord = new HashMap<>();
						oldRecord.put("ID", oldRecordId);
						oldRecord.put("Version", userApplyRecord.get("Version"));
						oldRecord.put("Updator", user.getId());
						oldRecord.put("UpdateTime", current);
						oldRecord.put("Status", GMApplyRecordStatus.RELIEVE.getStatus());
						oldRecord.put("DeauthorizeTime", current);
						oldRecord.put("ServiceUptodateType", "");
						oldRecord.put("DeauthorizeReason", "新权限审核通过，旧权限被自动解除");
						/**
						 * 将旧的权限申请置为解除状态
						 * 备注：将旧权限申请单由已审核更新为已解除状态，只是针对申请单里的权限变更成解除状态，
						 * 如果旧申请单中包含计次，那么计次不做解除仍然可以被使用
						 */
						int oldResult = gmApplyDao.updateApplyRecordByIdAndVersion(oldRecord);
						// 生成流水
						if(oldResult > 0) {
							
							// 理论上这个值不会为空
							Map<String, Object> oldFlowMap = gMApplyRecordFlowService.getNewestApplyRecordFlowByRecordId(MapUtils.getLong(userApplyRecord, "ID"));
							if(oldFlowMap == null) {
								oldFlowMap = new HashMap<>();
								oldFlowMap.put("ApplyRecordID", userApplyRecord.get("ID"));
								oldFlowMap.put("CompanyID", userApplyRecord.get("CompanyId"));
								oldFlowMap.put("ServiceStationID", userApplyRecord.get("ServiceStationId"));
							}
							/**
							 * 旧系统申请的权限记录，不生成操作流水，只对Guidanz-App申请的权限记录作操作流水
							 * 生成旧工单的操作流水
							 */
							oldFlowMap.put("ApplyRecordStatus", GMApplyRecordStatus.EXPIRE.getStatus());
							oldFlowMap.put("Description", GMApplyRecordStatus.EXPIRE.getDesc());
							oldFlowMap.put("Remark", "新权限审核通过，旧权限被自动解除");
							oldFlowMap.put("Creator", user.getId());
							oldFlowMap.put("CreateTime", current);
							// 保存对旧申请单的操作流水
							gMApplyRecordFlowService.saveApplyRecordFlow(oldFlowMap);
						}
					}else {
						hasBeta = true;
						// 只包含Beta权限
						if(oldServiceType.contains("BTGF") && !oldServiceType.contains("IAS0") && !oldServiceType.contains("SRV0")) {
							
							Map<String, Object> oldRecord = new HashMap<>();
							oldRecord.put("ID", oldRecordId);
							oldRecord.put("Version", oldVersion);
							oldRecord.put("Updator", user.getId());
							oldRecord.put("UpdateTime", current);
							oldRecord.put("Flag", -1);
							gmApplyDao.updateApplyRecordByIdAndVersion(oldRecord);
						}else {
							
							String ost =  oldServiceType.startsWith("BTGF") ? oldServiceType.replace("BTGF,", "") : oldServiceType.replace(",BTGF", "");
							
							Map<String, Object> oldRecord = new HashMap<>();
							oldRecord.put("ID", oldRecordId);
							oldRecord.put("Version", oldVersion);
							oldRecord.put("Updator", user.getId());
							oldRecord.put("UpdateTime", current);
							oldRecord.put("Status", GMApplyRecordStatus.RELIEVE.getStatus());
							oldRecord.put("DeauthorizeTime", current);
							oldRecord.put("ServiceUptodateType", "");
							oldRecord.put("ServiceType", ost);
							oldRecord.put("DeauthorizeReason", "新权限审核通过，旧权限被自动解除");
							int oldResult = gmApplyDao.updateApplyRecordByIdAndVersion(oldRecord);
							
							// 生成流水
							if(oldResult > 0) {
								
								// 理论上这个值不会为空
								Map<String, Object> oldFlowMap = gMApplyRecordFlowService.getNewestApplyRecordFlowByRecordId(oldRecordId);
								if(oldFlowMap == null) {
									oldFlowMap = new HashMap<>();
									oldFlowMap.put("ApplyRecordID", userApplyRecord.get("ID"));
									oldFlowMap.put("CompanyID", userApplyRecord.get("CompanyId"));
									oldFlowMap.put("ServiceStationID", userApplyRecord.get("ServiceStationId"));
								}
								/**
								 * 旧系统申请的权限记录，不生成操作流水，只对Guidanz-App申请的权限记录作操作流水
								 * 生成旧工单的操作流水
								 */
								oldFlowMap.put("ApplyRecordStatus", GMApplyRecordStatus.EXPIRE.getStatus());
								oldFlowMap.put("Description", GMApplyRecordStatus.EXPIRE.getDesc());
								oldFlowMap.put("Remark", "新权限审核通过，旧权限被自动解除");
								oldFlowMap.put("Creator", user.getId());
								oldFlowMap.put("CreateTime", current);
								// 保存对旧申请单的操作流水
								gMApplyRecordFlowService.saveApplyRecordFlow(oldFlowMap);
							}
							
						}
					}
					
				}else {
					
					// 是否包含未解除的Beta权限
					if(oldServiceUptodateType.contains("BTGF")) {
						hasBeta = true;
						
						String ost = oldServiceType.startsWith("BTGF") ? oldServiceType.replace("BTGF,", "") : oldServiceType.replace(",BTGF", "");
						
						Map<String, Object> oldRecord = new HashMap<>();
						oldRecord.put("ID", oldRecordId);
						oldRecord.put("Version", oldVersion);
						
						oldRecord.put("DeauthorizeTime", current);
						oldRecord.put("DeauthorizeReason", "新权限审核通过，旧权限被自动解除");
						oldRecord.put("Status", GMApplyRecordStatus.RELIEVE.getStatus());
						oldRecord.put("Updator", user.getId());
						oldRecord.put("UpdateTime", current);
						oldRecord.put("ServiceUptodateType", "");
						oldRecord.put("ServiceType", ost);
						gmApplyDao.updateApplyRecordByIdAndVersion(oldRecord);
					
					}else {
						gmApplyDao.releaseApplyRecordStatus(applyId, current, "新权限申请审批通过");
					}
					
					//更新用户的AD信息
					if(!updateADCustomerAttributes(applyName, type, null, null, "")) {
						log.error("AD权限修改失败："+user.getUserName());
					}
					
					//获取该申请人占用电子服务工具订单列表
					List<Long> orderList = gmApplyDao.getOccupiedOrderId(applyId);
					//释放被占用电子服务工具GM资源
					for(Long oid : orderList) {
						gmApplyDao.releaseOneResause(oid);
					}
				}
			}
			
		}
		
		String expireDate = getExpireDate(orderId);
		String newServiceType = userInfo.get("ServiceType").toString();
		//1. 修改申请记录状态及相关信息
		Map<String, Object> pMap = new HashMap<>();
		pMap.put("ID", recordId);
		pMap.put("OrderId", orderId);
		pMap.put("Status", 2);
		
		if(hasBeta) {
			newServiceType = newServiceType + ",BTGF";
			pMap.put("ServiceType", newServiceType);
			pMap.put("BTGFExpireDate", expireDate);
			pMap.put("BTGFSetTime", new Date());
		}
		pMap.put("ServiceUptodateType", newServiceType);
		pMap.put("HandlerId", user.getId());
		pMap.put("ExpireDate", expireDate);
		pMap.put("AuthorizeTime", current);
		pMap.put("Updator", user.getId());
		pMap.put("UpdateTime", current);
		gmApplyRecordTDao.updateGMApplyRecord(pMap);
		
		//2. 修改AD字段数据  
		updateADCustomerAttributes(applyName, type, 
			 type == INNER_TYPE ? userInfo.get("UserName").toString() : 
				                   "8" + String.format("%08d", Integer.valueOf(userInfo.get("ID").toString())), 
									
				                   userInfo.get("CompanyId").toString(), 
									getSWRegExpire(newServiceType, expireDate));
		
		
		
		//2. 通知申请人
		sendMsg(userInfo.get("Phone").toString(), userInfo.get("UserName").toString(), APPROVED_MSG);
		saveNotice(recordId, current, TO_APPLY, Long.valueOf(userInfo.get("ID").toString()), user.getId(), APPROVED_MSG);
		
		obj.put("data", "");
		obj.put("status", 0);
		obj.put("msg", "Success");
		ParameterTool.writeResponse(response, obj.toString());
		return null;
	}

	
	
	/**
	 * 提取用户基本信息
	 * @param request
	 * @return
	 */
	protected UserT getUserInfo(HttpServletRequest request) {
		String userid = request.getHeader("userid");
		
		userid = AESTool.decryptString(userid);// 解密userid
		
		UserT userT = (UserT) redisClientUtils.getObject("userT" + userid);
		
		if(null == userT) {
			userT = loginDao.getUserByid(userid);
			int redisCacheTime = Integer.valueOf(propertiesUtils.getPropertiesValue("redisCacheTime"));
			redisClientUtils.setObject("userT"+userT.getId(), userT, redisCacheTime);
		}

		return userT;
	}
	
	/**
	 * 获取控制开关
	 * @return
	 */
	protected String getGMControlFlag() {
		String flag = redisClientUtils.get("GMControlFlag");
		if(StringUtils.isNotBlank(flag)) {
			return flag;
		} else {
			return null;
		}
	}
	
	/**
	 * 验证企业是否授权
	 * @param companyId
	 * @param type
	 * @return
	 */
	protected boolean checkCompanyControl(Long companyId, int type) {
		int count = gmApplyDao.checkCompany(companyId, type);
		if(count > 0)
			return true;
		else 
			return false;
	}
	
	/**
	 * 获取GM服务等级
	 * @return
	 */
	protected List<Map<String, Object>> getSGSTList() {
		List<Map<String, Object>> list = new ArrayList<>();
		list = redisClientUtils.getObjectList("GMST");
		
		if(null == list) {
			list = gmApplyDao.getGMST();
			int redisCacheTime = Integer.valueOf(propertiesUtils.getPropertiesValue("redisCacheTime"));
			redisClientUtils.setObjectList("GMST", list, redisCacheTime);
		}
		return list;
	}
	
	/**
	 * 检查审核人并获取审核人信息
	 * @param user
	 * @return
	 */
	public List<Map<String, Object>> getAuditUser(UserT user) {
		List<Map<String, Object>> list = new ArrayList<>();
		if(user.getIsType() == 6) {
			//如果是服务商人员，审核人是服务站站长
			list = gmApplyDao.getStationAudit(user.getServiceStationID());
		} else {
			//如果是CCI或JV员工，审核人从配置表中获取
			list = gmApplyDao.getCompanyAudit(user.getUsergroupId());
		}
		return list;
	}
	
	/**
	 * 记录推送消息记录
	 * @param recordId
	 * @param current
	 * @param auditId
	 * @param applyId
	 * @param msg
	 */
	public void saveNotice(Long recordId, String current, int type, Long receiverId, Long senderId, String msg) {
		Map<String,Object> insertGMNotifyRecordData = new HashMap<>();
		insertGMNotifyRecordData.put("RecordId",recordId);
		insertGMNotifyRecordData.put("Type",type);
		insertGMNotifyRecordData.put("SendTime",current);
		insertGMNotifyRecordData.put("ReceiverId",receiverId);
		insertGMNotifyRecordData.put("MsgContent",msg);
		insertGMNotifyRecordData.put("Creator",senderId);
		insertGMNotifyRecordData.put("CreateTime",current);
		int result = gmApplyRecordTDao.insertGMNotifyRecordData(insertGMNotifyRecordData);
	}
	
	/**
	 * 
	 * @param map
	 * @param msg
	 * @return
	 */
	public boolean sendMsg(Map<String, Object> map, String msg) {
		try {
			sendMsg(map.get("Phone").toString(), map.get("UserName").toString(), msg);
			return true;
		} catch(Exception e) {
			return false;
		}
	}
	
	public void sendMsg(String receiverPhone, String receiverUserName, String msg) {
		if(StringUtils.isNotBlank(receiverPhone)) {
			SmsUtils.sendMessage(receiverPhone, msg);
		}
		if(StringUtils.isNotEmpty(receiverUserName)){
			String clientId = redisClientUtils.hget(RedisKeys.geTuiKey(), receiverUserName);
			if(StringUtils.isEmpty(clientId)) {
				// redis中不存在，查询数据库
				RelationShipT relationShipT = relationShipTDao.getClientIdByUserNameString(receiverUserName);
				if(null != relationShipT){
					clientId = relationShipT.getClientId();
				}
			}
			// 发送推送操作
			NotifyUtil.push2Single(clientId, "Guidanz权限申请提醒", msg, 2, msg);
		}
	}
	
	/**
	 * 修改AD中字段
	 * @param username       User -> username
	 * @param type           User -> type
	 * @param unionid        如果当前用户为内部用户 unionid -> username 否则 unionid -> userId
	 * @param workgroupid    用户的渠道id
	 * @param SWRegExpire    用户对应的权限以及过期时间 如  IAS0-05/09/2243|SRV0-05/09/2243|CMP0-05/09/2243
	 * @return
	 */
	public boolean updateADCustomerAttributes(String username, int type, String unionid, String workgroupid, String SWRegExpire) {
		String webClient_id = this.propertiesUtils.getPropertiesValue("webClient_id");
        String webClientSecret = this.propertiesUtils.getPropertiesValue("webClientSecret");
        String tenant = "";
        if(type == INNER_TYPE) {
        	tenant = this.propertiesUtils.getPropertiesValue("innerTenant");
        } else {
        	tenant = this.propertiesUtils.getPropertiesValue("tenant");
        }
        String unionid_field = this.propertiesUtils.getPropertiesValue("unionid_field");
        String workgroupid_field = this.propertiesUtils.getPropertiesValue("workgroupid_field");
        String SWRegExpire_field = this.propertiesUtils.getPropertiesValue("SWRegExpire_field");
        //获取token
        String token = AzureADTool.getManagementToken(tenant, webClient_id, webClientSecret);
        
        return AzureADTool.updateCustomAttributes(tenant, username, token, unionid_field, workgroupid_field, SWRegExpire_field, unionid, workgroupid, SWRegExpire);
	}
	
	/**
	 * 获取过期日期
	 * @param orderId
	 * @return
	 */
	private String getExpireDate(Long orderId) {
		if(null != orderId) {
			String expireTime = gmApplyDao.getExpireByOrderId(orderId);
			if(StringUtils.isNotBlank(expireTime)) {
				return expireTime.substring(0, 10);
			} else {
				return Date_Util.addDay(365);
			}
		} else {
			return Date_Util.addDay(365);
		}
	}
	
	private String getSWRegExpire(String serviceType, String expireDate) {
		String time = "-" + Date_Util.toString(Date_Util.toDate(expireDate, "yyyy-MM-dd"), "MM/dd/yyyy");
		String time_mid = time + "|";
		return serviceType.replaceAll(",", time_mid) + time;
	}

	
	public String getPeriodFromRds() {
		String period = redisClientUtils.get("GM_OVERTIME_PERIOD");
		if(StringUtils.isBlank(period)) {
			return "3";
		} else {
			return period;
		}
	}
	
	@Override
	public void overTimeNotice() {
		String current = LocalTimeUtil.getRealCurrentTime();
		List<Map<String, Object>> userList = gmApplyDao.getOverTimeList(current, getPeriodFromRds());
		
		userList.forEach(map -> {
			String applyName = "";String applyPhone = "";String auditName = "";String auditPhone = "";
			Long auditId = null;
			
			if(null != map.get("auditId") && StringUtils.isNotBlank(map.get("auditId").toString())) {
				auditId = Long.valueOf(map.get("auditId").toString());
			} else {
				return;
			}
			
			if(null != map.get("auditName")) {
				auditName = map.get("auditName").toString();
			}
			if(null != map.get("auditPhone")) {
				auditPhone = map.get("auditPhone").toString();
			}
			if(null != map.get("applyName")) {
				applyName = map.get("applyName").toString();
			}
			if(null != map.get("applyPhone")) {
				applyPhone = map.get("applyPhone").toString();
			}
			
			Long recordId = Long.valueOf(map.get("ID").toString());
			Long applyId = Long.valueOf(map.get("applyId").toString());
			
			String msg = String.format(TO_BE_APPROVED_OVERTIME_MSG, auditName, auditPhone);
			sendMsg(applyPhone, applyName, msg);
			saveNotice(recordId, current, TO_APPLY, applyId, null, msg);
		});
		
	}

	@Override
	public void setApplyOverTime() {
		//获取已超时的数据列表
		String current = LocalTimeUtil.getRealCurrentTime();
		List<Map<String, Object>> userList = gmApplyDao.getOverTimeUserList(current.substring(0, 10));
		//更新超时数据状态
		gmApplyDao.updateOverTimeFlag(current.substring(0, 10));
		
		//更新AD权限信息并发送消息提醒
		for(Map<String, Object> map: userList) {
			Long recordId = Long.valueOf(map.get("ID").toString());
			String applyPhone = map.get("applyPhone").toString();
			String applyName = map.get("applyName").toString();
			Long applyId = Long.valueOf(map.get("applyId").toString());
			int type = Integer.valueOf(map.get("Type").toString());
			//更新AD信息
			boolean flag = updateADCustomerAttributes(applyName, type, null, null, "");
			if(!flag) {
				log.error("到期GM权限用户AD数据修改失败！用户名：" + applyName + "; 申请记录主键：" + recordId);
			}
			//发送超时信息提醒
			sendMsg(applyPhone, applyName, OVERTIME_MSG);
			saveNotice(recordId, current, TO_APPLY, applyId, null, OVERTIME_MSG);
		}

		//添加15天前的提醒
        String time_15D = LocalTimeUtil.getTimeAfter(current, 14 * 24);
        List<Map<String, Object>> userList_15D = gmApplyDao.getOverTimeUserList(time_15D.substring(0, 10));

        //更新AD权限信息并发送消息提醒
        for(Map<String, Object> map: userList_15D) {
            Long recordId = Long.valueOf(map.get("ID").toString());
            String applyPhone = map.get("applyPhone").toString();
            String applyName = map.get("applyName").toString();
            Long applyId = Long.valueOf(map.get("applyId").toString());
            int type = Integer.valueOf(map.get("Type").toString());
            //更新AD信息
//            boolean flag = updateADCustomerAttributes(applyName, type, null, null, "");
//            if(!flag) {
//                log.error("到期GM权限用户AD数据修改失败！用户名：" + applyName + "; 申请记录主键：" + recordId);
//            }
            //发送超时信息提醒
			String msg = String.format(OVERTIME_MSG_15D, time_15D.substring(0, 10));
            sendMsg(applyPhone, applyName, msg);
            saveNotice(recordId, current, TO_APPLY, applyId, null, msg);
        }

        //添加30天前的提醒
        String time_30D = LocalTimeUtil.getTimeAfter(current, 29 * 24);
        List<Map<String, Object>> userList_30D = gmApplyDao.getOverTimeUserList(time_30D.substring(0, 10));

        //更新AD权限信息并发送消息提醒
        for(Map<String, Object> map: userList_30D) {
            Long recordId = Long.valueOf(map.get("ID").toString());
            String applyPhone = map.get("applyPhone").toString();
            String applyName = map.get("applyName").toString();
            Long applyId = Long.valueOf(map.get("applyId").toString());
            int type = Integer.valueOf(map.get("Type").toString());
            //更新AD信息
//            boolean flag = updateADCustomerAttributes(applyName, type, null, null, "");
//            if(!flag) {
//                log.error("到期GM权限用户AD数据修改失败！用户名：" + applyName + "; 申请记录主键：" + recordId);
//            }
            //发送超时信息提醒
			String msg = String.format(OVERTIME_MSG_30D, time_30D.substring(0, 10));
            sendMsg(applyPhone, applyName, msg);
            saveNotice(recordId, current, TO_APPLY, applyId, null, msg);
        }
	}

	@Override
	public void setGMDailyStatus() {
		redisClientUtils.delkey(RedisKeys.getRemindKey());
		List<String> statusList = gmApplyDao.getGMDailyStatus();
		if (statusList.size() > 0){
			redisClientUtils.setList(RedisKeys.getRemindKey(),statusList,Integer.valueOf(propertiesUtils.getPropertiesValue("redisCacheTime")));
		}
	}

	@Override
	public ModelAndView checkGMUsableNum(Map<String, Object> map) throws Exception {
		HttpServletResponse response = (HttpServletResponse) map.get("response");
		HttpServletRequest request = (HttpServletRequest) map.get("request");
		UserT user = getUserInfo(request);
		JSONObject obj = new JSONObject();
		//company!=1就是非cci
		Map<String,Object> userOrganizationType = userTDao.getUserOrganizationType(user.getId());
		int organizationType = 0;   //组织类型
		long organizationId = 0;   //组织id
		if(MapUtils.isNotEmpty(userOrganizationType)){
			int isType = MapUtils.getIntValue(userOrganizationType,"IsType");
			if(isType == 1 || isType == 3){
				organizationType = 1;
				organizationId = MapUtils.getLongValue(userOrganizationType,"CompanyID");
			} else if(isType == 6){
				organizationType = 2;
				organizationId = MapUtils.getLongValue(userOrganizationType,"ServiceStationID");
			}
		}
		//获取可用的订单    2.2.0需求
		int usableServiceToolOrderNum = gmApplyRecordTDao.getUsableServiceToolOrderNum(organizationType,organizationId);
		if (usableServiceToolOrderNum < 1){
			obj.put("data", "您的企业名称下无INSITE订单，无法授权Guidanz用户，请知悉");
			obj.put("status", 3);
			obj.put("msg", "您的企业名称下无INSITE订单，无法授权Guidanz用户，请知悉");
			ParameterTool.writeResponse(response, obj.toString());
			return null;
		}

		int usableGMNum = gmApplyRecordTDao.getUsableGMNum(organizationType,organizationId);
		if (usableGMNum > 0){
			obj.put("data", "");
			obj.put("status", 0);
			obj.put("msg", "Success");
			ParameterTool.writeResponse(response, obj.toString());
			return null;
		}
		obj.put("data", "");
		obj.put("status", 1);
		obj.put("msg", "您的企业名称下所有INSITE订单均已被授权，当前无INSITE订单可用，无法授权新Guidanz用户，请知悉");
		ParameterTool.writeResponse(response, obj.toString());
		return null;
	}

	/**
	 * 判断权限：我的-GM消息权限
	 * @param map
	 * @return
	 */
	@Override
	public ModelAndView checkGMAuthForMessage(Map<String, Object> map) {
		HttpServletResponse response = (HttpServletResponse) map.get("response");
		try {
			// 获取当前用户
			UserT userT = UserThreadLocal.get();
			JSONObject obj = new JSONObject();   //保存返给手机端的数据容器
			Map<String,Object> dataMap = new HashMap<>();   //保存data
			int gmAuth = 0;
			String flag = getGMControlFlag();
			if(StringUtils.isNotBlank(flag) && flag.equals("OPEN")) {
				//有进行企业权限验证，需要验证用户所属企业是不是在授权范围内
				boolean cheFlag;
				if(userT.getIsType() == 6) {
					cheFlag = checkCompanyControl(userT.getServiceStationID(), 2);
				} else {
					cheFlag = checkCompanyControl(userT.getCompanyId(), 1);
				}
				if(cheFlag) {
					gmAuth = checkUserGMAuth(userT);
				}
			}else {
				gmAuth = checkUserGMAuth(userT);
			}
			dataMap.put("gmAuth",gmAuth);
			obj.put("status","0");
			obj.put("msg","success");
			obj.put("data",dataMap);
			ParameterTool.writeResponse(response, obj.toString());
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
			ParameterTool.writeErrorResponse(response);
		}
		return null;
	}

	private Integer checkUserGMAuth(UserT userT) {
		int gmAuth = 0;
		// 判断是否为站长
		Long headerStatus =  userTDao.checkHeaderStatusById(userT.getId());
		if (null != headerStatus){
			gmAuth = 1;
		}
		//判断是否为审批人
		Long approverStatus = userTDao.checkApproverStatusById(userT.getId());
		if (null != approverStatus){
			gmAuth = 1;
		}
		//判断是否有Guidanz权限
		int authStatus = gmApplyDao.checkUserApply2(userT.getId());
		if (authStatus != 0 ){
			gmAuth = 1;
		}
		return gmAuth;
	}
}
